package com.jianxiu.utils;

import java.io.OutputStream;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletResponse;

import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.util.CollectionUtils;

import com.jianxiu.bean.xls.ExcelData;
import com.jianxiu.bean.xls.ExcelEntity;
import com.jianxiu.bean.xls.ExcelHeader;
import com.jianxiu.bean.xls.ExcelSheet;

/**
 * Created by tancw on 2015/8/24.
 */
public class ExportUtil {

    /**
     * 数据表格生成
     *
     * @param response
     * @param fileName  导出文件名
     * @param data      查询结果集
     * @param clazz     实体类
     * @param sheetname 表单名
     */
    public static void exportSimpExcel(HttpServletResponse response, String fileName, List data, Class clazz, String sheetname) {
        OutputStream out = null;
        try {
            response.setCharacterEncoding("utf-8");
            response.setContentType("multipart/form-data");
            response.setHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("utf-8"), "iso8859-1"));
            Workbook workbook = handleDataToExcel(data, clazz, sheetname);
            out = response.getOutputStream();
            workbook.write(out);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取表格头部与表格数据,返回表格对象
     *
     * @param data
     * @param clazz
     * @param sheetname
     * @return
     * @throws Exception
     */
    private static Workbook handleDataToExcel(List data, Class clazz, String sheetname) throws Exception {
        List<ExcelHeader> headers = getHeaderList(clazz);
        // 按order排序
        Collections.sort(headers);

        List<String> headLst = new ArrayList<String>();
        for (ExcelHeader head : headers) {
            headLst.add(head.getTitle());
        }

        String headAry[] = headLst.toArray(new String[headers.size()]);
        List<List<String>> contentLst = new ArrayList<List<String>>();

        for (Object obj : data) {
            List<String> col = new ArrayList<String>();
            for (ExcelHeader head : headers) {
                Method method = clazz.getDeclaredMethod(head.getMethodName());
                Object value = method.invoke(obj);
                if (value instanceof BigDecimal) {
                    col.add(((BigDecimal) value).toPlainString());
                } else if (value instanceof Date) {
                    col.add(new SimpleDateFormat(head.getFormat()).format((Date) value));
                } else {
                    col.add(String.valueOf(value));
                }
            }
            contentLst.add(col);
        }

        return getExcelWork(sheetname, headAry, contentLst);
    }

    /**
     * 根据表格名，表格头，表格内容获取表格work
     *
     * @param sheetname
     * @param head
     * @param contentlst
     * @return
     */
    private static Workbook getExcelWork(String sheetname, String[] head, List<List<String>> contentlst) {
        ExcelSheet excelSheet = ExcelUtils2.createExcelSheet(sheetname, head, contentlst);
        List<ExcelSheet> sheetList = new ArrayList<ExcelSheet>();
        sheetList.add(excelSheet);
        ExcelEntity excelEntity = new ExcelEntity();
        excelEntity.setSheetList(sheetList);
        return ExcelUtils2.writeExcel2003(excelEntity);
    }

    ;

    /**
     * 根据注解获取表格对象
     *
     * @param clazz
     * @return
     */
    private static List<ExcelHeader> getHeaderList(Class clazz) {
        //优先匹配属性上的
        List<ExcelHeader> headers = matchField(clazz);
        if (!CollectionUtils.isEmpty(headers)) return headers;
        //属性匹配不上匹配方法
        return matchMethod(clazz);
    }

    /**
     * 根据class获取注解在属性上的信息
     *
     * @param clazz
     * @return
     */
    private static List<ExcelHeader> matchField(Class clazz) {
        List<ExcelHeader> headers = new ArrayList<ExcelHeader>();
        java.lang.reflect.Field[] fs = clazz.getDeclaredFields();
        for (java.lang.reflect.Field f : fs) {
            if (f.isAnnotationPresent(ExcelData.class)) {
                ExcelData dataMapper = f.getAnnotation(ExcelData.class);
                String getName = String.format("get%s%s", f.getName().substring(0, 1).toUpperCase(), f.getName().substring(1));
                headers.add(new ExcelHeader(dataMapper.title(), dataMapper.order(), dataMapper.format(), getName));
            }
        }
        return headers;
    }

    /**
     * 根据class获取注解在方法上的信息
     *
     * @param clazz
     * @return
     */
    private static List<ExcelHeader> matchMethod(Class clazz) {
        List<ExcelHeader> headers = new ArrayList<ExcelHeader>();
        Method[] ms = clazz.getDeclaredMethods();
        for (Method m : ms) {
            String mn = m.getName();
            if (mn.startsWith("get")) {
                if (m.isAnnotationPresent(ExcelData.class)) {
                    ExcelData dataMapper = m.getAnnotation(ExcelData.class);
                    headers.add(new ExcelHeader(dataMapper.title(), dataMapper.order(), dataMapper.format(), mn));
                }
            }
        }
        return headers;
    }
}
